package demo.aop.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.Arrays;

@Aspect
@Slf4j
@Component //必须是个bean
public class DemoAspect {

    //前置通知
    @Before("execution (* demo.aop.controller.AdviceKindTestController.*(..))")
    public void auth() {
        log.info("前置通知，假装校验了个权限");
    }

    //后置通知
    //returning参数会引用 连接点方法最后返回的值
    @AfterReturning(value = "execution (* demo.aop.controller.AdviceKindTestController.*(..))",returning = "obj")
    public  void   afterSomething(Object obj){

        //引入连接点的返回结果
        log.info("后置通知，不太清楚运用场景  {}",obj.toString());
    }

    //环绕通知
    //如果环绕通知 不返回执行结果  方法不会返回任何结果，导致接口拿不到任何数据
    //所以一定把proceed 返回
    //ProceedingJoinPoint 是 JoinPoint的子类，仅当环绕通知的时候，可以注入ProceedingJoinPoint的连接点
    @Around("execution (* demo.aop.controller.AdviceKindTestController.*(..))")
    public  Object  getMethodTime(ProceedingJoinPoint point) throws Throwable {
        log.info("环绕通知，统计方法耗时，方法执行前");
        Long beforeMillis = System.currentTimeMillis();
        Object proceed = point.proceed();
        Long taketimes= System.currentTimeMillis()-beforeMillis;
        log.info(String.format("该方法用时%s毫秒",taketimes));
        return proceed;
    }

    //异常通知
    @AfterThrowing("execution (* demo.aop.controller.AdviceKindTestController.*(..))")
    public void throwSomething() {
        log.info("异常通知，只有异常了才会通知。具体场景，不是特别了解");
    }

    //最终通知
    @After("execution (* demo.aop.controller.AdviceKindTestController.*(..))")
    public void closeSomething() {
        log.info("最终通知，官网说，可以用来回收某些资源。无论发不发生异常，都会被执行");
    }



}
